I have too many ticks on my graph and they are running into each other.
How can I reduce the number of ticks?
For example, I have ticks:
1E-6, 1E-5, 1E-4, ... 1E6, 1E7
And I only want:
1E-5, 1E-3, ... 1E5, 1E7
I've tried playing with the LogLocator
, but I haven't been able to figure this out.
10 Answers 10
Alternatively, if you want to simply set the number of ticks while allowing matplotlib to position them (currently only with MaxNLocator
), there is pyplot.locator_params
,
pyplot.locator_params(nbins=4)
You can specify specific axis in this method as mentioned below, default is both:
# To specify the number of ticks on both or any single axes
pyplot.locator_params(axis='y', nbins=6)
pyplot.locator_params(axis='x', nbins=10)
-
38This was a great suggestion, also being able to specify
pyplot.locator_params(axis = 'x', nbins = 4)
(oraxis = 'y'
) made the process really straightforward. Thanks @bgamari!benjaminmgross– benjaminmgross2012年12月28日 19:40:48 +00:00Commented Dec 28, 2012 at 19:40 -
13With log scale, this worked with
numticks
instead ofnbins
meduz– meduz2016年05月19日 10:01:46 +00:00Commented May 19, 2016 at 10:01 -
19This doesn't seem to place the labels where they should be. For example, if the original tick labels are
[0, 1, ..., 99]
and now one setsnticks=10
, then the new sparse labels will be placed ten times as long apart along the axis, i.e. now1
will sit where9
was,2
where19
was... and9
where99
was.Vim– Vim2018年03月08日 02:35:52 +00:00Commented Mar 8, 2018 at 2:35 -
5Check your results before trusting this method. @Vim is correct. The tick values will be placed incorrectly.David J.– David J.2019年01月31日 01:34:58 +00:00Commented Jan 31, 2019 at 1:34
-
2I got incorrect labeling with this method, but @Katerina's worked as expected.ldmtwo– ldmtwo2020年11月04日 22:05:19 +00:00Commented Nov 4, 2020 at 22:05
To solve the issue of customisation and appearance of the ticks, see the Tick Locators guide on the matplotlib website
ax.xaxis.set_major_locator(plt.MaxNLocator(3))
would set the total number of ticks in the x-axis to 3, and evenly distribute them across the axis.
There is also a nice tutorial about this
-
Only select first 3 datetime index. when get ax from pandas.DataFrame.plot
ax = df.plot()
Mithril– Mithril2019年11月01日 02:27:49 +00:00Commented Nov 1, 2019 at 2:27 -
@Mithril sorry I don't quite understand your comment. Could you please elaborate?Prageeth Jayathissa– Prageeth Jayathissa2019年11月04日 02:59:18 +00:00Commented Nov 4, 2019 at 2:59
-
1If I have a df (
pandas.DataFrame
) with datetime index [2019年01月01日, ...2019年11月01日], callax = df.plot()
, return a figure object . callax.xaxis.set_major_locator(plt.MaxNLocator(3))
only show first 3 index [2019年01月01日, 2019年01月02日, 2019年01月03日] .Mithril– Mithril2019年11月04日 05:57:32 +00:00Commented Nov 4, 2019 at 5:57 -
3@Mithril,
df.plot()
often displays theminor_locator
, so you might want to tryax1.xaxis.set_minor_locator(plt.MaxNLocator(3))
. Also remember to substitute the3
for the number of ticks that you want to display. For pandas timeseries I recommendimport matplotlib.dates as mdates
and runax.xaxis.set_minor_locator(mdates.MonthLocator(interval = 1))
withax.xaxis.set_minor_formatter(mdates.DateFormatter('%m-%Y'))
Prageeth Jayathissa– Prageeth Jayathissa2019年11月04日 11:18:59 +00:00Commented Nov 4, 2019 at 11:18 -
As I had a lot of datapoints to plot, pyplot was printing a lot (>500) ticks per axis. This heavily slowed down the plotting process. By reducing the number of thicks with
set_major_locator(5)
the plotting process is much faster.Sparkofska– Sparkofska2020年08月11日 09:27:06 +00:00Commented Aug 11, 2020 at 9:27
If somebody still gets this page in search results:
fig, ax = plt.subplots()
plt.plot(...)
every_nth = 4
for n, label in enumerate(ax.xaxis.get_ticklabels()):
if n % every_nth != 0:
label.set_visible(False)
-
6In my case with pandas and numerically spaced, this is working as is expected while locator_params(nbins) and plt.MaxNLocator give a strange behavior.Joonho Park– Joonho Park2021年02月22日 10:59:09 +00:00Commented Feb 22, 2021 at 10:59
-
3This works for non-numerical x axis labels, which is helpfuljgholder– jgholder2021年10月28日 21:29:10 +00:00Commented Oct 28, 2021 at 21:29
There's a set_ticks()
function for axis objects.
-
4This would work if I knew beforehand what ticks I wanted. The example I gave above was only an example. I don't know what the ticks are, I just know I want fewer of them, i.e., every other one.jlconlin– jlconlin2011年07月13日 17:28:10 +00:00Commented Jul 13, 2011 at 17:28
-
12You could call
get_xticks()
orget_yticks()
first for the axes object, edit as needed, and then pass the list back toset_ticks()
.user812786– user8127862011年07月13日 17:44:08 +00:00Commented Jul 13, 2011 at 17:44 -
4I don't have
set_ticks()
, but I do haveset_xticks()
andset_yticks()
. These are attributes of axes objects, not axis. Maybe this has changed during the last couple of years.Gauthier– Gauthier2013年06月11日 08:01:29 +00:00Commented Jun 11, 2013 at 8:01 -
2I am not sure if I should, some people have found your answer useful as is, and just because it is different for me does not mean it is for everybody.Gauthier– Gauthier2013年06月12日 07:24:10 +00:00Commented Jun 12, 2013 at 7:24
-
8An example would go a long way towards making this answer useful.Richard– Richard2018年05月31日 23:00:05 +00:00Commented May 31, 2018 at 23:00
in case somebody still needs it, and since nothing here really worked for me, i came up with a very simple way that keeps the appearance of the generated plot "as is" while fixing the number of ticks to exactly N:
import numpy as np
import matplotlib.pyplot as plt
f, ax = plt.subplots()
ax.plot(range(100))
ymin, ymax = ax.get_ylim()
ax.set_yticks(np.round(np.linspace(ymin, ymax, N), 2))
-
3I had to modify the last line slightly in order to get it to return the values as int instead of float:
ax.set_yticks(np.linspace(int(ymin), int(ymax), N), 2)
Nick Settje– Nick Settje2018年09月07日 09:01:20 +00:00Commented Sep 7, 2018 at 9:01 -
@NickSettje still floats with me!Mohd– Mohd2020年07月07日 17:12:59 +00:00Commented Jul 7, 2020 at 17:12
The solution @raphael gave is straightforward and quite helpful.
Still, the displayed tick labels will not be values sampled from the original distribution but from the indices of the array returned by np.linspace(ymin, ymax, N)
.
To display N values evenly spaced from your original tick labels, use the set_yticklabels()
method. Here is a snippet for the y axis, with integer labels:
import numpy as np
import matplotlib.pyplot as plt
ax = plt.gca()
ymin, ymax = ax.get_ylim()
custom_ticks = np.linspace(ymin, ymax, N, dtype=int)
ax.set_yticks(custom_ticks)
ax.set_yticklabels(custom_ticks)
If you need one tick every N=3 ticks :
N = 3 # 1 tick every 3
xticks_pos, xticks_labels = plt.xticks() # get all axis ticks
myticks = [j for i,j in enumerate(xticks_pos) if not i%N] # index of selected ticks
newlabels = [label for i,label in enumerate(xticks_labels) if not i%N]
or with fig,ax = plt.subplots()
:
N = 3 # 1 tick every 3
xticks_pos = ax.get_xticks()
xticks_labels = ax.get_xticklabels()
myticks = [j for i,j in enumerate(xticks_pos) if not i%N] # index of selected ticks
newlabels = [label for i,label in enumerate(xticks_labels) if not i%N]
(obviously you can adjust the offset with (i+offset)%N
).
Note that you can get uneven ticks if you wish, e.g. myticks = [1, 3, 8]
.
Then you can use
plt.gca().set_xticks(myticks) # set new X axis ticks
or if you want to replace labels as well
plt.xticks(myticks, newlabels) # set new X axis ticks and labels
Beware that axis limits must be set after the axis ticks.
Finally, you may wish to draw only an arbitrary set of ticks :
mylabels = ['03/2018', '09/2019', '10/2020']
plt.draw() # needed to populate xticks with actual labels
xticks_pos, xticks_labels = plt.xticks() # get all axis ticks
myticks = [i for i,j in enumerate(xticks_labels) if j.get_text() in mylabels]
plt.xticks(myticks, mylabels)
(assuming mylabels
is ordered ; if it is not, then sort myticks
and reorder it).
-
1there is a little error in the last code block. One of the lines should be written as:
myticks = [i for i,j in enumerate(xticks_labels) if j.get_text() in mylabels]
gtristan– gtristan2023年08月22日 12:54:41 +00:00Commented Aug 22, 2023 at 12:54 -
@gtristan Right, fixed, thanks !Skippy le Grand Gourou– Skippy le Grand Gourou2023年08月24日 15:30:52 +00:00Commented Aug 24, 2023 at 15:30
xticks function auto iterates with range function
start_number = 0
end_number = len(data you have)
step_number = how many skips to make from strat to end
rotation = 90 degrees tilt will help with long ticks
plt.xticks(range(start_number,end_number,step_number),rotation=90)
-
I came to contribute a range based solution. Your example is much more concise. But to add to it, you can use the shape to get what you want eg
plt.xticks(range(0, df.shape[0], 12),rotation=90)
Joe Still– Joe Still2022年08月22日 22:01:06 +00:00Commented Aug 22, 2022 at 22:01
if you want 10 ticks:
for y axis: ax.set_yticks(ax.get_yticks()[::len(ax.get_yticks())//10])
for x axis: ax.set_xticks(ax.get_xticks()[::len(ax.get_xticks())//10])
this simply gets your ticks and chooses every 10th of the list and sets it back to your ticks. you can change the number of ticks as you wish.
When a log scale is used the number of major ticks can be fixed with the following command
import matplotlib.pyplot as plt
....
plt.locator_params(numticks=12)
plt.show()
The value set to numticks
determines the number of axis ticks to be displayed.
Credits to @bgamari's post for introducing the locator_params()
function, but the nticks
parameter throws an error when a log scale is used.
-
The question and answer are for previous matplotlib, i.e. 1, and you're referring to 2.Dawid Laszuk– Dawid Laszuk2017年12月17日 01:49:44 +00:00Commented Dec 17, 2017 at 1:49
-
I do not think an argument called 'numticks' exists.troymyname00– troymyname002022年03月06日 21:36:31 +00:00Commented Mar 6, 2022 at 21:36
-
Kindly refer the matplotlib doc for numticks @troymyname00Ébe Isaac– Ébe Isaac2022年03月07日 02:53:32 +00:00Commented Mar 7, 2022 at 2:53